import * as Blockly from 'blockly/core';
import * as Mixly from 'mixly';
import * as $ from 'jquery';
import BlockTool from '../blockTool';

const { Editor } = Mixly;

const generators = {};

const Generator = Blockly.Arduino ?? Blockly.Python;

let oldInitFuncStr = '';
let oldGeneratorFuncStr = '';
let oldXMLStr = '';

generators.block_tool_main = function () {
    const CHECKBOX_SHOW_CODE = this.getFieldValue('SHOW_CODE') == 'TRUE';
    const CHECKBOX_SHOW_BLOCKS_XML = this.getFieldValue('SHOW_BLOCKS_XML') == 'TRUE';
    const TEXT_NAME = this.getFieldValue('NAME');
    const STATEMENTS_BLOCK = Generator.statementToCode(this, 'BLOCK').split('\n');
    const DROPDOWN_INPUT_TYPE = this.getFieldValue('INPUT_TYPE');
    const DROPDOWN_CONNECT_TYPE = this.getFieldValue('CONNECT_TYPE');
    const VALUE_TOOLTIP = Generator.valueToCode(this, 'TOOLTIP', Generator.ORDER_ATOMIC);
    const VALUE_HELP_URL = Generator.valueToCode(this, 'HELP_URL', Generator.ORDER_ATOMIC);
    const VALUE_COLOR = Generator.valueToCode(this, 'COLOR', Generator.ORDER_ATOMIC);
    const STATEMENTS_GENERATOR = Generator.statementToCode(this, 'GENERATOR');
    const STATEMENTS_XML = Generator.statementToCode(this, 'XML');
    let blockCodeList = [];
    let generatorCodeList = [];
    for (let elemStr of STATEMENTS_BLOCK) {
        if (!elemStr) {
            continue;
        }
        let elemObj;
        try {
            elemObj = JSON.parse(elemStr)
        } catch (error) {
            elemObj = null;
        }
        if (!elemObj) {
            continue;
        }
        elemObj.block = elemObj.block ?? [];
        elemObj.generator = elemObj.generator ?? [];
        for (let i of elemObj.block) {
            blockCodeList.push(i);
        }
        for (let i of elemObj.generator) {
            generatorCodeList.push(i);
        }
    }

    switch (DROPDOWN_INPUT_TYPE) {
    case 'OUT_LINE':
        blockCodeList.push('this.setInputsInline(false);');
        break;
    case 'IN_LINE':
        blockCodeList.push('this.setInputsInline(true);');
        break;
    }

    switch (DROPDOWN_CONNECT_TYPE) {
    case 'TOP':
        blockCodeList.push('this.setPreviousStatement(true, null);');
        break;
    case 'BOTTOM':
        blockCodeList.push('this.setNextStatement(true, null);');
        break;
    case 'V_BOTH':
        blockCodeList.push('this.setPreviousStatement(true, null);');
        blockCodeList.push('this.setNextStatement(true, null);');
        break;
    case 'LEFT':
        blockCodeList.push('this.setOutput(true, null);');
        break;
    }

    if (isNaN(VALUE_COLOR - 0)) {
        blockCodeList.push(`this.setColour("${VALUE_COLOR}");`);
    } else {
        blockCodeList.push(`this.setColour(${VALUE_COLOR});`);
    }

    blockCodeList.push(`this.setTooltip(${VALUE_TOOLTIP});`);
    blockCodeList.push(`this.setHelpUrl(${VALUE_HELP_URL});`);
    let initFuncStr = blockCodeList.join('\n        ');
    let blockCode = `Blockly.Blocks.${TEXT_NAME} = {\n`
                  + '    init: function () {\n'
                  + `        ${initFuncStr}\n`
                  + '    }\n'
                  + '};\n';
    BlockTool.blockCode = blockCode;
    BlockTool.ace.block && BlockTool.ace.block.setValue(blockCode, -1);
    let xmlCode = `<block type="${TEXT_NAME}">\n`;
    let $block = $(`<xml><block type="${BlockTool.BLOCK_TOOL_VIEW_TYPE}">${STATEMENTS_XML}</block></xml>`);
    if (!$block.length) {
        xmlCode += BlockTool.BLOCK_TOOL_VIEW_XML;
        $block = $(`<xml>${BlockTool.BLOCK_TOOL_VIEW_XML}</xml>`);
    } else {
        xmlCode += STATEMENTS_XML;
    }
    xmlCode += '</block>';
    let updated = false;
    let isError = false;
    BlockTool.xmlCode = xmlCode;
    BlockTool.ace.xml && BlockTool.ace.xml.setValue(xmlCode, -1);
    if (oldInitFuncStr !== initFuncStr) {
        let blockList = this.workspace.getBlocksByType('block_tool_view');
        for (let block of blockList) {
            block.dispose(false);
        }
        Blockly.Blocks.block_tool_view = {
            init: function() {
                try {
                    eval(initFuncStr);
                } catch (error) {
                    isError = true;
                    BlockTool.$error.html(error.name + ' - ' + error.message);
                    if (BlockTool.DEBUG) {
                        console.log(error);
                    }
                }
            }
        };
        if (BlockTool.workspace) {
            BlockTool.workspace.clear();
            try {
                Blockly.Xml.domToWorkspace($block[0], BlockTool.workspace);
            } catch (error) {
                isError = true;
                BlockTool.$error.html(error.name + ' - ' + error.message);
                $block = $(`<xml>${BlockTool.BLOCK_TOOL_VIEW_XML}</xml>`);
                Blockly.Xml.domToWorkspace($block[0], BlockTool.workspace);
                if (BlockTool.DEBUG) {
                    console.log(error);
                }
            }
            // BlockTool.workspace.scrollCenter();
        }
        updated = true;
        oldInitFuncStr = initFuncStr;
    }
    if (oldXMLStr !== xmlCode && !updated) {
        if (BlockTool.workspace) {
            BlockTool.workspace.clear();
            try {
                Blockly.Xml.domToWorkspace($block[0], BlockTool.workspace);
            } catch (error) {
                isError = true;
                BlockTool.$error.html(error.name + ' - ' + error.message);
                $block = $(`<xml>${BlockTool.BLOCK_TOOL_VIEW_XML}</xml>`);
                Blockly.Xml.domToWorkspace($block[0], BlockTool.workspace);
                if (BlockTool.DEBUG) {
                    console.log(error);
                }
            }
            // BlockTool.workspace.scrollCenter();
        }
        updated = true;
        oldXMLStr = xmlCode;
    }
    let generatorFuncStr = '';
    let generatorCode = '';
    let generatorType = '';
    if (Blockly.Arduino) {
        generatorType = 'Blockly.Arduino';
    } else {
        generatorType = 'Blockly.Python';
    }
    generatorCode += `${generatorType}.forBlock.${TEXT_NAME} = function () {\n`;
    if (generatorCodeList.length) {
        generatorFuncStr = generatorCodeList.join('\n    ');
        generatorCode += `    ${generatorFuncStr}\n`;
        generatorCode += STATEMENTS_GENERATOR;
    }
    if (DROPDOWN_CONNECT_TYPE === 'LEFT') {
        generatorCode += `    return ["", ${generatorType}.ORDER_ATOMIC];\n`;
    } else {
        generatorCode += '    return "";\n';
    }
    generatorCode += '};\n';
    BlockTool.generatorCode = generatorCode;
    BlockTool.ace.generator && BlockTool.ace.generator.setValue(generatorCode, -1);

    if (oldGeneratorFuncStr !== generatorFuncStr) {
        Generator.block_tool_view = function () {
            try {
                eval(generatorFuncStr);
            } catch (error) {
                isError = true;
                BlockTool.$error.html(error.name + ' - ' + error.message);
                if (BlockTool.DEBUG) {
                    console.log(error);
                }
            }
            if (DROPDOWN_CONNECT_TYPE === 'LEFT') {
                return ['', Generator.ORDER_ATOMIC];
            }
            return '';
        };
        oldGeneratorFuncStr = generatorFuncStr;
    }

    if (!isError) {
        BlockTool.$error && BlockTool.$error.html('无错误');
    }

    if (CHECKBOX_SHOW_CODE) {
        if (Blockly.Python) {
            Generator.definitions_['define_block_tool_view_block'] = blockCode;
            Generator.definitions_['define_block_tool_view_generator'] = generatorCode;
        } else {
            Generator.definitions_['import__block_tool_view_block'] = blockCode;
            Generator.definitions_['import_block_tool_view_generator'] = generatorCode;
        }
    }

    let xmlDom = Blockly.Xml.workspaceToDom(Editor.blockEditor);
    let $xml = $(xmlDom);
    $xml.find('block,shadow').removeAttr('id varid x y');
    $xml.find('block[type="block_tool_main"]').remove();
    let xmlStr = Blockly.Xml.domToPrettyText($xml[0]);
    BlockTool.ace.blocksXml && BlockTool.ace.blocksXml.setValue(xmlStr, -1);
    if (CHECKBOX_SHOW_BLOCKS_XML) {
        if (Blockly.Python) {
            Generator.definitions_['define_block_tool_show_xml'] = xmlStr;
        } else {
            Generator.definitions_['import_block_tool_show_xml'] = xmlStr;
        }
    }
    return '';
};

export default generators;